﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TETRIS_v01.FieldObjects;
using TETRIS_v01.GameHost.GameSounds;
using System.Threading;


namespace TETRIS_v01.GameHost
{
    public class GameLogic
    {
        private bool gameOn = true;
        private bool pauseOff = true;
        private bool afterPause = false;
        private InputHandlerBase _userInputHandler;
        private Field _playingField;
        private Shape _playingShape;
        SoundPlayer soundPlayer = new SoundPlayer();

        public GameLogic(InputHandlerBase inputHandler)
        {
            _userInputHandler = inputHandler;
        }
        
        private bool IsBottomFree(Field f,Shape anyShape, int step)
        {
            anyShape.MoveBottom(step);
            anyShape.CollectBlocks();
            foreach (Block b in anyShape._shapeBlocks)
            {
                if (b.y > f.StartPoint.y + f.FieldHeight || f._gameCellsStatus[b.x - (f.StartPoint.x + 1), b.y - (f.StartPoint.y + 1)] == 1)
                { anyShape.MoveBottom(-step); return false; }
            }
            anyShape.MoveBottom(-step); return true;// bottom is free for move
        }

        private bool IsRightFree(Field f, Shape anyShape)
        {
            anyShape.MoveRight(1);
            anyShape.CollectBlocks();
            foreach (Block b in anyShape._shapeBlocks)
            {
                if (b.x > f.StartPoint.x + f.FieldWidth || b.y <= f.StartPoint.y || f._gameCellsStatus[b.x - (f.StartPoint.x + 1), b.y - (f.StartPoint.y + 1)] == 1)
                { anyShape.MoveLeft(1); return false; }
            }
            anyShape.MoveLeft(1); return true;// right is free for move
        }

        private bool IsLeftFree(Field f, Shape anyShape)
        {
            anyShape.MoveLeft(1);
            anyShape.CollectBlocks();
            foreach (Block b in anyShape._shapeBlocks)
            {
                if (b.x <= f.StartPoint.x || b.y <= f.StartPoint.y || f._gameCellsStatus[b.x - (f.StartPoint.x + 1), b.y - (f.StartPoint.y + 1)] == 1)
                { anyShape.MoveRight(1); return false; }
            }
            anyShape.MoveRight(1); return true;// right is free for move
        }

        private bool IsRotationAvailable(Field f, Shape anyShape)
        {   
            anyShape.Rotate(1);
            anyShape.CollectBlocks();
            foreach (Block b in anyShape._shapeBlocks)
            {
                if (b.x <= f.StartPoint.x || b.x > f.StartPoint.x + f.FieldWidth || b.y <= f.StartPoint.y || b.y > f.StartPoint.y + f.FieldHeight || f._gameCellsStatus[b.x - (f.StartPoint.x + 1), b.y - (f.StartPoint.y + 1)] == 1)
                { anyShape.Rotate(3); return false; }
            }
            anyShape.Rotate(3); return true;// right is free for move
        }


        private void SendGameMessage(string text, ConsoleColor textColor, ConsoleColor frameColor, int startX, int startY)
        {
            Frame fr = new Frame();
            fr.SetFrame(frameColor, startX, startY, startX + text.Length + 3, startY + 2);
            Console.SetCursorPosition(startX+2, startY+1);
            Console.ForegroundColor = textColor;
            Console.Write("{0}",text);
            Console.ResetColor();
        }

        public void StartGame(Field f)
        {
            _playingField = f;            
            Frame fr = new Frame();
            InfoBoard gameInfoBoard = new InfoBoard(f);
            ShapeGenerator shGenerator = new ShapeGenerator();
            //SoundPlayer soundPlayer = new SoundPlayer();
            int figureCounter = 0;

            Console.SetWindowSize(f.FieldWidth + 34, f.FieldHeight + 6);
            fr.SetFrameExtended(f.FrameColor, f.StartPoint.x, f.StartPoint.y, f.StartPoint.x + f.FieldWidth + 1,
                                f.StartPoint.y + f.FieldHeight + 1, '░', '░', '☺', '☺', '☺', '☺');//'░', '░', '☺', '☺', '☺', '☺'
            //fr.SetFrame(f.FrameColor, f.StartPoint.x, f.StartPoint.y, f.StartPoint.x + f.FieldWidth + 1,f.StartPoint.y + f.FieldHeight + 1);
            
            _userInputHandler.MoveRight += OnMoveRightRequest;
            _userInputHandler.MoveLeft += OnMoveLeftRequest;
            _userInputHandler.Rotate += OnRotateRequest;
            _userInputHandler.MoveDown += OnMoveDownRequest;
            _userInputHandler.FastMoveDown += OnFastDownRequest;
            _userInputHandler.Pause += OnPauseRequest;

            //soundPlayer.StartMusic();
            //soundPlayer.playSound("D:\\Sounds\\indi.wav");

            do
            {                
                List<int> fullRowsNumbers = _playingField.FindFullRows();
                if (fullRowsNumbers.Count > 0)
                {
                    _playingField.PrintField(ConsoleColor.Yellow);
                    _playingField.PrintFullRows(fullRowsNumbers, ConsoleColor.Red);
                    _playingField.DeleteFullRows(fullRowsNumbers);
                    soundPlayer.KilledRowsSound(fullRowsNumbers.Count);
                    Thread.Sleep(200);                    
                }
                
                gameInfoBoard.RefreshBoard(fullRowsNumbers.Count, figureCounter, shGenerator.ShapeStack);
                gameInfoBoard.DrawInfoBoard(_playingField); //прорисовывать шапки отдельно
                _playingField.PrintField(ConsoleColor.Yellow);
                _playingShape = shGenerator.ShapeStack[0];                
                _playingShape.InitFieldPosition(f);
                int eventInterval = 0;

                while (IsBottomFree(f, _playingShape,1))
                {
                    _userInputHandler.QueryKeyBoard();
                    if (pauseOff)
                    {
                        if (afterPause) 
                        {
                            _playingField.PrintField(ConsoleColor.Yellow);
                            afterPause = false;
                        }
                        
                        _playingShape.MoveBottom(1);
                        _playingField.ClearField();
                        _playingShape.PrintShape();
                        if (eventInterval > 4) { gameInfoBoard.ClearEvents(); }
                        Thread.Sleep(gameInfoBoard.GameSpeed);
                        eventInterval++;
                    }
                    else
                    {
                        SendGameMessage("PAUSE", ConsoleColor.Green, ConsoleColor.DarkGreen, f.StartPoint.x + f.FieldWidth / 2 - 3, f.StartPoint.y + f.FieldHeight / 2);
                    } 
                }
                soundPlayer.BottomSound();
                _playingShape.CollectBlocks();
                foreach (Block b in _playingShape._shapeBlocks)
                {
                    if (b.y - (f.StartPoint.y + 1) >= 0)
                    {
                        f._gameCellsStatus[b.x - (f.StartPoint.x + 1), b.y - (f.StartPoint.y + 1)] = 1;
                    }
                    else { gameOn = false; }
                }
                
                figureCounter++;
                shGenerator.AddNewShape();
            }
            while(gameOn);   //пока не переполнится до верха поле    
            
            SendGameMessage("GAME OVER", ConsoleColor.Red, ConsoleColor.Red, f.StartPoint.x + f.FieldWidth / 2 - 5, f.StartPoint.y + f.FieldHeight / 2);
            soundPlayer.GameOverMusic();
        }

        private void OnMoveRightRequest(object sender, EventArgs e)
        {
            if (IsRightFree(_playingField, _playingShape))
            {
                _playingShape.MoveRight(1);
            }
        }

        private void OnMoveLeftRequest(object sender, EventArgs e)
        {
            if (IsLeftFree(_playingField, _playingShape))
            {
                _playingShape.MoveLeft(1);
            }
        }

        private void OnMoveDownRequest(object sender, EventArgs e)
        {
            if (IsBottomFree(_playingField, _playingShape,1))
            {
                _playingShape.MoveBottom(1);
            }
        }
        private void OnRotateRequest(object sender, EventArgs e)
        {
            if (IsRotationAvailable(_playingField, _playingShape))
            {
                _playingShape.Rotate(1);
            }
        }
        private void OnPauseRequest(object sender, EventArgs e)
        {
            if (pauseOff)  { pauseOff = false;   }
            else           { pauseOff = true; afterPause = true; }
            soundPlayer.PauseSound();
        }

        private void OnFastDownRequest(object sender, EventArgs e)
        {
            while (IsBottomFree(_playingField, _playingShape, 1))
            {
                _playingShape.MoveBottom(1);
            }
            //_playingShape.MoveBottom(-1);
        }

    }
}
